import javax.persistence.Entity
import javax.persistence.Column
import java.lang.reflect.Field
import java.text.SimpleDateFormat

/**
 * Created by IntelliJ IDEA.
 * User: HP_Administrator
 * Date: Sep 4, 2008
 * Time: 10:31:15 PM
 * To change this template use File | Settings | File Templates.
 */
class EntityParser {

    def parse(Class clz, BeanData data) {
        if (!clz.isAnnotationPresent(Entity.class)) {
            throw new RuntimeException("Class $clz is not an entity")
        }

        def instance = clz.newInstance()
        data.keySet().each { key ->
            def field = findField(clz, key)
            if (field == null) {
                throw new NoSuchFieldException("Could not find field $key on clz")
            }
            setField(instance, field, data.get(key))
        }
        return instance
    }

    def findField(clz, key) {
        def field = findFieldByFieldName(clz, key)
        if (field == null) {
            field = findFieldByColumn(clz, key)
        }
        return field
    }

    def findFieldByFieldName(Class clz, fieldName) {
        if (clz.equals(Object.class)) {
            return null
        }
        try {
            Field field = clz.getDeclaredField(fieldName)
            field.accessible = true;
            return field
        } catch (NoSuchFieldException) {
            return findFieldByFieldName(clz.superclass, fieldName)
        }
    }

    def setField(instance, field, String value) {
        switch (field.type) {
            case String.class:
                field.set(instance, value)
                break;
            case Integer.class:
                field.set(instance, value.toInteger())
                break;
            case Double.class:
                field.set(instance, value.toDouble())
                break;
            case Date.class:
                def format = new SimpleDateFormat('yyyy-MM-dd')
                field.set(instance, format.parse(value))
                break;
            default:
                throw new RuntimeException('Unsupported type ' + field.type.name)
        }
    }

    def findFieldByColumn(Class clz, String columnName) {
        for (method in clz.methods) {
            def columnAnnotation = method.getAnnotation(Column.class)
            if (columnAnnotation != null) {
                if (method.getAnnotation(Column.class).name() == columnName) {
                    def fieldName = method.name - 'get'
                    def firstChar = fieldName.substring(0,1).toLowerCase()
                    fieldName = firstChar + fieldName.substring(1)
                    return findFieldByFieldName(clz, fieldName)
                }
            }
        }
    }
}